﻿using System;
using System.Runtime.CompilerServices;
using Runtime.Services.Battle;
using UnityEngine;

namespace Runtime.Services.BattleAttack {

    internal sealed partial class DFR_BattleAttackService {

        private static readonly F64 MAX = F64.Hundred;

        public bool IsPointInRectangle(DFR_BattleMapPosition rectCenter, F64 rectRange, DFR_BattleMapPosition point) {
            rectRange = F64.Min(MAX, rectRange);
            var size = rectRange * 2 + F64.One + BATTLE_COLLISION_RECTANGLE_ADD_SIZE;
            var halfSize = size * F64.Half;
            var p1 = new Vector2F64(rectCenter.X - halfSize, rectCenter.Y - halfSize);
            var p2 = new Vector2F64(rectCenter.X + halfSize, rectCenter.Y - halfSize);
            var p3 = new Vector2F64(rectCenter.X + halfSize, rectCenter.Y + halfSize);
            var p4 = new Vector2F64(rectCenter.X - halfSize, rectCenter.Y + halfSize);
            var result = CollisionCheck.IsPointInQuad(p1, p2, p3, p4, point);
            return result;
        }

        private class CollisionCheck {

            // 判断点是否在三角形内
            private static bool IsPointInTriangle(Vector2F64 a, Vector2F64 b, Vector2F64 c, Vector2F64 p) {
                var v0 = c - a;
                var v1 = b - a;
                var v2 = p - a;

                var dot00 = Vector2F64.Dot(v0, v0);
                var dot01 = Vector2F64.Dot(v0, v1);
                var dot02 = Vector2F64.Dot(v0, v2);
                var dot11 = Vector2F64.Dot(v1, v1);
                var dot12 = Vector2F64.Dot(v1, v2);

                var invDenom = F64.One / (dot00 * dot11 - dot01 * dot01);
                var u = (dot11 * dot02 - dot01 * dot12) * invDenom;
                var v = (dot00 * dot12 - dot01 * dot02) * invDenom;

                var result = (u >= 0) && (v >= 0) && (u + v < 1);
                return result;
            }

            // 检测点是否在四边形内
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            public static bool IsPointInQuad(Vector2F64 p1, Vector2F64 p2, Vector2F64 p3, Vector2F64 p4, Vector2F64 point) {
                return IsPointInTriangle(p1, p2, p3, point) || IsPointInTriangle(p1, p3, p4, point);
            }
        }
    }
}
